this fixes memory leak in garmin_gpi, and adds a test.
enhance testing of pretty_deg_format to get coverage of dms.
char* strip_nastyhtml(const QString& in);
char* convert_human_date_format(const char* human_datef); /* "MM,YYYY,DD" -> "%m,%Y,%d" */
char* convert_human_time_format(const char* human_timef); /* "HH+mm+ss" -> "%H+%M+%S" */
-char* pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html); /* decimal -> dd.dddd or dd mm.mmm or dd mm ss */
+QString pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html); /* decimal -> dd.dddd or dd mm.mmm or dd mm ss */
QString get_filename(const QString& fname); /* extract the filename portion */
str = wpt->notes;
}
} else if (opt_pos) {
- str = pretty_deg_format(wpt->latitude, wpt->longitude, 's', " ", 0);
+ str = pretty_deg_format(wpt->latitude, wpt->longitude, 's', " ", false);
}
*fout << "#####\n";
fatal(MYNAME ": %s (%s) is outside of convertible area \"%s\"!\n",
wpt->shortname.isEmpty() ? "Waypoint" : qPrintable(wpt->shortname),
- pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, 0),
+ qPrintable(pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, false)),
gt_get_mps_grid_longname(grid_index, MYNAME));
}
}
gbfprintf(file_out, "\n<a name=\"%s\"><hr></a>\n", CSTR(wpt->shortname));
gbfprintf(file_out, "<table width=\"100%%\">\n");
gbfprintf(file_out, "<tr><td><p class=\"gpsbabelwaypoint\">%s - ",(global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname));
- char* cout = pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", 1);
- gbfprintf(file_out, "%s (%d%c %6.0f %7.0f)", cout, utmz, utmzc, utme, utmn);
- xfree(cout);
+ gbfprintf(file_out, "%s (%d%c %6.0f %7.0f)",
+ CSTR(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", true)),
+ utmz, utmzc, utme, utmn);
if (wpt->altitude != unknown_alt) {
gbfprintf(file_out, " alt:%d", (int)((altunits[0]=='f')?METERS_TO_FEET(wpt->altitude):wpt->altitude));
}
if (logpart) {
double lat = xml_attribute(logpart->attributes, "lat").toDouble();
double lon = xml_attribute(logpart->attributes, "lon").toDouble();
- char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 1);
gbfprintf(file_out,
"<span class=\"gpsbabellogcoords\">%s</span><br>\n",
- coordstr);
- xfree(coordstr);
+ CSTR(pretty_deg_format(lat, lon, degformat[2], " ", true)));
}
logpart = xml_findfirst(curlog, "groundspeak:text");
--- /dev/null
+lat|lon|desc
+0.134°S|0.135°W|point0
+0.134°N|0.135°E|point1
+1.134°S|1.135°W|point2
+1.134°N|1.135°E|point3
+10.134°S|10.135°W|point4
+10.134°N|10.135°E|point5
+80.134°S|100.135°W|point6
+80.134°N|100.135°E|point7
--- /dev/null
+No,Latitude,Longitude,Name\r
+1,S0.13400,W0.13500,"point0"\r
+2,N0.13400,E0.13500,"point1"\r
+3,S1.13400,W1.13500,"point2"\r
+4,N1.13400,E1.13500,"point3"\r
+5,S10.13400,W10.13500,"point4"\r
+6,N10.13400,E10.13500,"point5"\r
+7,S80.13400,W100.13500,"point6"\r
+8,N80.13400,E100.13500,"point7"\r
--- /dev/null
+No,Latitude,Longitude,Name\r
+1,S0 08.040,W0 08.100,"point0"\r
+2,N0 08.040,E0 08.100,"point1"\r
+3,S1 08.040,W1 08.100,"point2"\r
+4,N1 08.040,E1 08.100,"point3"\r
+5,S10 08.040,W10 08.100,"point4"\r
+6,N10 08.040,E10 08.100,"point5"\r
+7,S80 08.040,W100 08.100,"point6"\r
+8,N80 08.040,E100 08.100,"point7"\r
--- /dev/null
+No,Latitude,Longitude,Name\r
+1,"S0 08'02.4""","W0 08'06.0""","point0"\r
+2,"N0 08'02.4""","E0 08'06.0""","point1"\r
+3,"S1 08'02.4""","W1 08'06.0""","point2"\r
+4,"N1 08'02.4""","E1 08'06.0""","point3"\r
+5,"S10 08'02.4""","W10 08'06.0""","point4"\r
+6,"N10 08'02.4""","E10 08'06.0""","point5"\r
+7,"S80 08'02.4""","W100 08'06.0""","point6"\r
+8,"N80 08'02.4""","E100 08'06.0""","point7"\r
gpsbabel -i gpx -f ${REFERENCE}/garmin_gpi.gpx -o garmin_gpi,category="Vinícolas",hide -F ${TMPDIR}/garmin_gpi_category~gpx.gpi
compare ${REFERENCE}/garmin_gpi_category~gpx.gpi ${TMPDIR}/garmin_gpi_category~gpx.gpi
+# check position option
+gpsbabel -i gpx -f ${REFERENCE}/garmin_gpi.gpx -o garmin_gpi,position -F ${TMPDIR}/garmin_gpi_position~gpx.gpi
+compare ${REFERENCE}/garmin_gpi_position~gpx.gpi ${TMPDIR}/garmin_gpi_position~gpx.gpi
+
# check dual language read
# spb_metro_norm.gpi from https://www.garmin.ru/download/extras/poi.php or https://files.navicom.ru/spb_metro_norm.gpi
gpsbabel -i garmin_gpi,languagecode=RU -f ${REFERENCE}/spb_metro_norm.gpi -o gpx -F ${TMPDIR}/spb_metro_norm_ru~gpi.gpx
compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec1.gpx
gpsbabel -i unicsv -f ${REFERENCE}/humantodec2.csv -o gpx -F ${TMPDIR}/humantodec2.gpx
compare ${REFERENCE}/humantodec.gpx ${TMPDIR}/humantodec2.gpx
+
+# pretty degree format
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=0 -F ${TMPDIR}/pretty_degree0.csv
+compare ${REFERENCE}/pretty_degree0.csv ${TMPDIR}/pretty_degree0.csv
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=1 -F ${TMPDIR}/pretty_degree1.csv
+compare ${REFERENCE}/pretty_degree1.csv ${TMPDIR}/pretty_degree1.csv
+gpsbabel -i unicsv -f ${REFERENCE}/pretty_degree.csv -o unicsv,grid=2 -F ${TMPDIR}/pretty_degree2.csv
+compare ${REFERENCE}/pretty_degree2.csv ${TMPDIR}/pretty_degree2.csv
GPS_Math_WGS84_To_UTM_EN(wpt->latitude, wpt->longitude,
&utme, &utmn, &utmz, &utmzc);
- char* tmpout1 = pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", 0);
if (wpt->altitude != unknown_alt) {
xasprintf(&altout, " alt:%d", (int)((altunits[0]=='f')?METERS_TO_FEET(wpt->altitude):wpt->altitude));
} else {
altout = (char*) "";
}
- xasprintf(&tmpout2, "%s (%d%c %6.0f %7.0f)%s", tmpout1, utmz, utmzc, utme, utmn, altout);
+ xasprintf(&tmpout2, "%s (%d%c %6.0f %7.0f)%s",
+ CSTR(pretty_deg_format(wpt->latitude, wpt->longitude, degformat[2], " ", false)),
+ utmz, utmzc, utme, utmn, altout);
gbfprintf(file_out, "%-16s %59s\n",
(global_opts.synthesize_shortnames) ? CSTR(mkshort_from_wpt(mkshort_handle, wpt)) : CSTR(wpt->shortname),
tmpout2);
xfree(tmpout2);
- xfree(tmpout1);
if (altout[0]) {
xfree(altout);
}
if (logpart) {
double lat = xml_attribute(logpart->attributes, "lat").toDouble();
double lon = xml_attribute(logpart->attributes, "lon").toDouble();
- char* coordstr = pretty_deg_format(lat, lon, degformat[2], " ", 0);
- gbfprintf(file_out, "%s\n", coordstr);
- xfree(coordstr);
+ gbfprintf(file_out, "%s\n",
+ CSTR(pretty_deg_format(lat, lon, degformat[2], " ", false)));
}
logpart = xml_findfirst(curlog, "groundspeak:text");
*fout << "#####\n";
fatal(MYNAME ": %s (%s) is outside of convertible area of grid \"%s\"!\n",
wpt->shortname.isEmpty() ? "Waypoint" : qPrintable(wpt->shortname),
- pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, 0),
+ qPrintable(pretty_deg_format(wpt->latitude, wpt->longitude, 'd', nullptr, false)),
gt_get_mps_grid_longname(unicsv_grid_idx, MYNAME));
}
UnicsvFormat::unicsv_waypt_disp_cb(const Waypoint* wpt)
{
double lat, lon, alt;
- char* cout = nullptr;
const geocache_data* gc_data = nullptr;
unicsv_waypt_ct++;
switch (unicsv_grid_idx) {
case grid_lat_lon_ddd:
- cout = pretty_deg_format(lat, lon, 'd', unicsv_fieldsep, 0);
- *fout << cout;
+ *fout << pretty_deg_format(lat, lon, 'd', unicsv_fieldsep, false);
break;
case grid_lat_lon_dmm:
- cout = pretty_deg_format(lat, lon, 'm', unicsv_fieldsep, 0);
- *fout << cout;
+ *fout << pretty_deg_format(lat, lon, 'm', unicsv_fieldsep, false);
break;
case grid_lat_lon_dms: {
- cout = pretty_deg_format(lat, lon, 's', unicsv_fieldsep, 0);
- char* sep = strchr(cout, ',');
- *sep = '\0';
- QString tmp = csv_enquote(cout, kUnicsvQuoteChar);
+ QString position = pretty_deg_format(lat, lon, 's', unicsv_fieldsep, false);
+ auto sep = position.indexOf(unicsv_fieldsep);
+ QString tmp = csv_enquote(position.left(sep), kUnicsvQuoteChar);
*fout << tmp << unicsv_fieldsep;
- tmp = csv_enquote(sep+1, kUnicsvQuoteChar);
+ tmp = csv_enquote(position.mid(sep+1), kUnicsvQuoteChar);
*fout << tmp;
}
break;
break;
}
- if (cout) {
- xfree(cout);
- }
-
if FIELD_USED(fld_shortname) {
unicsv_print_str(shortname);
}
* sep = string between lat and lon (separator)
* html = 1 for html output otherwise text
*/
-char*
-pretty_deg_format(double lat, double lon, char fmt, const char* sep, int html)
+QString
+pretty_deg_format(double lat, double lon, char fmt, const char* sep, bool html)
{
- char* result;
+ QString result;
char latsig = lat < 0 ? 'S':'N';
char lonsig = lon < 0 ? 'W':'E';
int latint = abs((int) lat);
sep = " "; /* default " " */
}
if (fmt == 'd') { /* ddd */
- xasprintf(&result, "%c%6.5f%s%s%c%6.5f%s",
- latsig, fabs(lat), html?"°":"", sep,
- lonsig, fabs(lon), html?"°":"");
+ result = QStringLiteral("%1%2%3%4%5%6%7")
+ .arg(latsig).arg(fabs(lat), 6, 'f', 5).arg(html ? "°" : "", sep)
+ .arg(lonsig).arg(fabs(lon), 6, 'f', 5).arg(html ? "°" : "");
} else if (fmt == 's') { /* dms */
- xasprintf(&result, "%c%d%s%02d'%04.1f\"%s%c%d%s%02d'%04.1f\"",
- latsig, latint, html?"°":" ", (int)latmin, latsec, sep,
- lonsig, lonint, html?"°":" ", (int)lonmin, lonsec);
+ result = QStringLiteral("%1%2%3%4'%5\"%6%7%8%9%10'%11\"")
+ .arg(latsig).arg(latint).arg(html ? "°" : " ").arg((int)latmin, 2, 10, QChar('0')).arg(latsec, 4, 'f', 1, QChar('0')).arg(sep)
+ .arg(lonsig).arg(lonint).arg(html ? "°" : " ").arg((int)lonmin, 2, 10, QChar('0')).arg(lonsec, 4, 'f', 1, QChar('0'));
} else { /* default dmm */
- xasprintf(&result, "%c%d%s%06.3f%s%c%d%s%06.3f",
- latsig, latint, html?"°":" ", latmin, sep,
- lonsig, lonint, html?"°":" ", lonmin);
+ result = QStringLiteral("%1%2%3%4%5%6%7%8%9")
+ .arg(latsig).arg(latint).arg(html ? "°" : " ").arg(latmin, 6, 'f', 3, QChar('0')).arg(sep)
+ .arg(lonsig).arg(lonint).arg(html ? "°" : " ").arg(lonmin, 6, 'f', 3, QChar('0'));
}
return result;
}